﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;

namespace YasharEl.Infrastructure.ServiceBus.Unicast.Subscriptions
{
    /// <summary>
    /// Defines storage for subscriptions
    /// </summary>
    [ContractClass(typeof(SubscriptionStorageContract))]
    public interface ISubscriptionStorage
    {
        /// <summary>
        /// Subscribes the given client address to messages of the given types.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="messageTypes"></param>
        void Subscribe(Address client, IEnumerable<MessageType> messageTypes);

        /// <summary>
        /// Unsubscribes the given client address from messages of the given types.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="messageTypes"></param>
        void Unsubscribe(Address client, IEnumerable<MessageType> messageTypes);

        /// <summary>
        /// Returns a list of addresses of subscribers that previously requested to be notified
        /// of messages of the given message types.
        /// </summary>
        /// <param name="messageTypes"></param>
        /// <returns></returns>
        IEnumerable<Address> GetSubscriberAddressesForMessage(IEnumerable<MessageType> messageTypes);

        /// <summary>
        /// Notifies the subscription storage that now is the time to perform
        /// any initialization work
        /// </summary>
        void Init();
    }

    [ContractClassFor(typeof(ISubscriptionStorage))]
    internal abstract class SubscriptionStorageContract : ISubscriptionStorage
    {
        #region ISubscriptionStorage Members

        public void Subscribe(Address client, IEnumerable<MessageType> messageTypes)
        {
            Contract.Requires<ArgumentNullException>(client != null, "client could not be null.");
            Contract.Requires<ArgumentNullException>(messageTypes != null, "messageTypes could not be null.");
        }

        public void Unsubscribe(Address client, IEnumerable<MessageType> messageTypes)
        {
            Contract.Requires<ArgumentNullException>(client != null, "client could not be null.");
            Contract.Requires<ArgumentNullException>(messageTypes != null, "messageTypes could not be null.");
        }

        public IEnumerable<Address> GetSubscriberAddressesForMessage(IEnumerable<MessageType> messageTypes)
        {
            Contract.Requires<ArgumentNullException>(messageTypes != null, "messageTypes could not be null.");
            return new List<Address>();
        }

        public void Init()
        {
        }

        #endregion
    }
}
